#define RUNTIME_DBG_LVL			0
#include <dbg/ptest.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <metalc/base/mtls.h>
#include <metalc/mlos/mmapheap.h>
#include <pthreadalt.h>


#include "apds_common.h"
#include <unix/page_alloc_os.h>

/* 定义slab */
#include <metalc/mlayer/slab_lk.h>
DEF_CLS_TC(tc, 3, 14)

DEF_SLAB_MLAYER(slab, 3, 14, tc, BIT(17), 4, mlcc_palloc)

#include <metalc/mladt/bulk.h>

/* mmap heap*/
DEF_MMAPHEAP_MLAYER(mmapheap_normal, 2 * 1024 * 1024, SIZE_1G, SIZE_64G, 1, 0)
/* 组合 */
COMPOSE_MLAYER(test_slab, slab, bulk, mmapheap_normal)

/* 定义tls */
DEF_MTLS_PTHREAD(GET_MLAYER_OBJNR(test_slab), 4096, mlcc_palloc, mp_coreid)

/* 定义初始化过程 */
#include <pthreadalt/pthreadalt_init.h>
DEF_PTHREADALT_INIT
DEF_SYSINIT(mtls, testnode, test_slab)
DEF_CFLOWFIN(mtls)
DEF_CFLOWINIT(mtls, test_slab)
DEF_SYSFIN(__omega)

/* 测试 */

#define TEST_MAXTHREADS	(24)
#define TEST_NR		(1000000)

#define TEST_MINSIZE	(1)
#define TEST_MAXSIZE	(256)
#define TEST_SET	(0)
#define TEST_ALLOC	test_slab_alloc
#define TEST_FREE	test_slab_free
#define TEST_SIZEOF	test_slab_sizeof


static void *bench_slab(void *args){
	PARAM_USED(args);
	mreq_t req;
	for (word_t idx = 0; idx < TEST_NR; idx++){
		size_t rqsize = TEST_MINSIZE + hash(idx + rdcnt_relax()) % (TEST_MAXSIZE - TEST_MINSIZE);
		mreq_setalloc(&req, rqsize, 0);
		uvoid *umem = TEST_ALLOC(&req);
		void *mem = req.ptr;
		// assert(umem);
		
		assert(umem);
		req.ptr = umem;
		size_t size = TEST_SIZEOF(&req);
		assert(size >= rqsize);
		PARAM_USED(umem, mem, size);
		if (TEST_SET) {
			__memset(umem, 0xff, rqsize);
			// INFO("memset [%p - %p]\n", umem, umem + usize);
		}
		req.nr = 1;
		TEST_FREE(&req);
	}
	return NULL;
}
PERF_PARALLEL_FUNC_THREADNR(bench_slab, TEST_NR * 2, TEST_MAXTHREADS)

void test_slab_basic(){
	mreq_t req;
	void *mem;
	mreq_setalloc(&req, 16, 0);
	mem = test_slab_alloc(&req);

	req.ptr = mem;
	size_t sz = test_slab_sizeof(&req);
	assert(sz >= 16);

	bool_t s = test_slab_free(&req);
	assert(s == TRUE);

}
static void test_slab_end(){
	dbg_printf("slab bench ok\n");
}
/* perf测试 */
int main(){
	test_slab_basic();
	dbg_printf("now bench slab\n");
	PERF_PARALLEL_RUN(bench_slab);
	test_slab_end();
	return 0;
}